package com.gcloud.mesh.dcs.task;

import com.gcloud.mesh.asset.dao.IaasDao;
import com.gcloud.mesh.asset.dao.NodeDao;
import com.gcloud.mesh.asset.entity.IaasEntity;
import com.gcloud.mesh.asset.entity.NodeEntity;
import com.gcloud.mesh.asset.enums.DeviceType;
import com.gcloud.mesh.dcs.dao.AliPowerDao;
import com.gcloud.mesh.dcs.entity.AliPowerEntity;
import com.gcloud.mesh.dcs.enums.AliPowerDeviceType;
import com.gcloud.mesh.header.enums.MonitorMeter;
import com.gcloud.mesh.header.enums.ResourceSourceType;
import com.gcloud.mesh.header.vo.supplier.AliPower.AliPowerDeviceDenamicVo;
import com.gcloud.mesh.header.vo.supplier.AliPower.AliPowerDeviceMapVo;
import com.gcloud.mesh.header.vo.supplier.AliPower.AliPowerDeviceVo;
import com.gcloud.mesh.monitor.dao.StatisticsDao;
import com.gcloud.mesh.monitor.entity.StatisticsEntity;
import com.gcloud.mesh.supplier.adapter.AliPowerConsumptionAdapter;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.stream.Collectors;

@Component
@Slf4j
public class SyncAliPowerTask {
    private final AliPowerConsumptionAdapter aliPowerAdapter;
    private final AliPowerDao aliPowerDao;
    private final IaasDao iaasDao;
    private final NodeDao nodeDao;
    private final StatisticsDao statisticsDao;

    @Autowired
    public SyncAliPowerTask(AliPowerConsumptionAdapter aliPowerAdapter, AliPowerDao aliPowerDao, IaasDao iaasDao, NodeDao nodeDao, StatisticsDao statisticsDao) {
        this.aliPowerAdapter = aliPowerAdapter;
        this.aliPowerDao = aliPowerDao;
        this.iaasDao = iaasDao;
        this.nodeDao = nodeDao;
        this.statisticsDao = statisticsDao;
    }


    @Scheduled(initialDelay = 1000 * 60 * 5, fixedDelay = 1000 * 60 * 5)
    public void work() throws ParseException {
        log.info("[SyncAliPowerTask] 开始同步阿里功耗平台数据");
        List<AliPowerDeviceVo> devices = aliPowerAdapter.getAllDevices();
        if (devices.isEmpty()) {
            log.info("[SyncAliPowerTask] 不存在同步的数据");
        }
        for (AliPowerDeviceVo device : devices) {
            if (!AliPowerDeviceType.contains(device.getType())) {
                log.info("[SyncAliPowerTask]设备{}的类型为{}，不在采集范围内", device.getId(), device.getType());
                continue;
            }
            AliPowerDeviceMapVo nodeDetail = aliPowerAdapter.detailNode(device.getId());
            AliPowerDeviceDenamicVo deviceDenamic = aliPowerAdapter.deviceDenamic(device.getId());
            if (nodeDetail == null || deviceDenamic == null) {
                log.info("[SyncAliPowerTask]无法获取到设备{}的详细信息", device.getId());
                continue;
            }
            AliPowerEntity aliPowerEntity = new AliPowerEntity();
            log.info("[SyncAliPowerTask]正在同步设备:{},数据中心为:{},功耗为：{}", device.getId(), device.getAddress(),deviceDenamic.getPower());
            aliPowerEntity.setEsn(device.getId())
                    .setDeviceModel(nodeDetail.getDevice_model())
                    .setDeviceManufacturer(nodeDetail.getMaintenance_provider())
                    .setDatacenterId(device.getAddress())
                    .setCreateTime(nodeDetail.getCreate_time())
                    .setMgmIp(nodeDetail.getIp())
                    .setIpmiIp(nodeDetail.getOob_ip())
                    .setHostname(nodeDetail.getHost_name())
                    .setPowerStatus(Objects.equals(nodeDetail.getUsage_status(), "running") ? 1 : 0)
                    .setPowerConsumption(Float.valueOf(deviceDenamic.getPower()));
            AliPowerEntity existAliPowerEntity = aliPowerDao.findOneByProperty("esn", nodeDetail.getDevice_id());
            if (existAliPowerEntity == null) {
                aliPowerEntity.setId(UUID.randomUUID().toString());
                aliPowerDao.save(aliPowerEntity);
            } else {
                aliPowerEntity.setId(existAliPowerEntity.getId());
                aliPowerDao.update(aliPowerEntity);
            }

            log.info("[SyncAliPowerTask]开始同步数据到iaas,nodes表中");
            //如果不存在，新增iaas和node表数据;如果存在，则去查node表
            IaasEntity iaasEntity = iaasDao.findOneByProperty("esn", aliPowerEntity.getEsn());
            NodeEntity nodeEntity = new NodeEntity();
            if (iaasEntity == null) {
                iaasEntity = new IaasEntity();
            } else {
                NodeEntity tempNodeEntity = nodeDao.findOneByProperty("id", iaasEntity.getDeviceId());
                if (tempNodeEntity != null) {
                    nodeEntity = tempNodeEntity;
                }
            }
            //机柜
            Map<String, Object> param = new HashMap<>(2);
            param.put("esn", nodeDetail.getLocated_cabinet());
            param.put("type", DeviceType.CABINET.getNo());
            IaasEntity cabinetDb = iaasDao.findOneByProperties(param);
            String cabinetId = UUID.randomUUID().toString();
            if (cabinetDb != null) {
                cabinetId = cabinetDb.getId();
            } else {
                Map<String, String> cabinet = aliPowerAdapter.detailDevice(nodeDetail.getLocated_cabinet(), aliPowerEntity.getDatacenterId());
                if (cabinet != null && !cabinet.isEmpty()) {
                    IaasEntity newCabinet = new IaasEntity();
                    newCabinet.setId(cabinetId);
                    newCabinet.setEsn(nodeDetail.getLocated_cabinet());
                    newCabinet.setDatacenterId(aliPowerEntity.getDatacenterId());
                    newCabinet.setName(nodeDetail.getLocated_cabinet());
                    newCabinet.setDeviceManufacturer(cabinet.get("manufacturer"));
                    newCabinet.setDeviceModel(cabinet.get("device_model"));
                    newCabinet.setFrom(ResourceSourceType.SYNC.getName());
                    newCabinet.setType(DeviceType.CABINET.getNo());
                    newCabinet.setCreateTime(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").parse(cabinet.get("create_time")));
                    newCabinet.setVisible(true);
                    iaasDao.save(newCabinet);
                    log.info("[SyncAliPowerTask]同步方式新增机柜{}", cabinetId);
                } else {
                    cabinetId = null;
                }
            }

            //数据通过处理，所以通过id是否为空来判断数据不存在还是存在于数据库中
            nodeEntity.setMgmIp(aliPowerEntity.getMgmIp());
            nodeEntity.setIpmiIp(aliPowerEntity.getIpmiIp());
            nodeEntity.setHostname(aliPowerEntity.getHostname());
            nodeEntity.setPowerStatus(aliPowerEntity.getPowerStatus());
            nodeEntity.setPowerConsumption(aliPowerEntity.getPowerConsumption());
            nodeEntity.setCabinetId(cabinetId);
            if (StringUtils.isEmpty(nodeEntity.getId())) {
                nodeEntity.setId(UUID.randomUUID().toString());
                nodeDao.save(nodeEntity);
            } else {
                nodeDao.update(nodeEntity);
            }

            iaasEntity.setEsn(aliPowerEntity.getEsn());
            iaasEntity.setDeviceModel(aliPowerEntity.getDeviceModel());
            iaasEntity.setDeviceManufacturer(aliPowerEntity.getDeviceManufacturer());
            iaasEntity.setDatacenterId(aliPowerEntity.getDatacenterId());
            iaasEntity.setCreateTime(aliPowerEntity.getCreateTime());
            iaasEntity.setName(aliPowerEntity.getEsn());
            iaasEntity.setType(DeviceType.SERVER.getNo());
            iaasEntity.setDeviceId(nodeEntity.getId());
            iaasEntity.setFrom(ResourceSourceType.SYNC.getName());
            iaasEntity.setVisible(true);
            if (StringUtils.isEmpty(iaasEntity.getId())) {
                iaasEntity.setId(UUID.randomUUID().toString());
                iaasDao.save(iaasEntity);
            } else {
                iaasDao.update(iaasEntity);
            }


            syncToStatistics(iaasEntity.getId(), deviceDenamic, nodeDetail);

        }
        log.info("[SyncAliPowerTask] 结束同步阿里功耗平台数据");

        //如果表中的服务器已经不在功耗平台，则需要移除;nodeIdsInPlatforms功耗平台存在的服务器
        log.info("[SyncAliPowerTask]开始清除表中多余的服务器");
        List<String> nodeIdsInPlatforms = devices.stream()
                .map(AliPowerDeviceVo::getId)
                .collect(Collectors.toList());
        List<String> delNodeIds = aliPowerDao.findAll().stream()
                .map(AliPowerEntity::getEsn)
                .filter(esn -> !nodeIdsInPlatforms.contains(esn))
                .collect(Collectors.toList());
        for (String delNodeId : delNodeIds) {
            aliPowerDao.deleteByEsn(delNodeId);
        }
        log.info("[SyncAliPowerTask]结束清除表中多余的服务器，服务器列表为:{}", delNodeIds);
    }


    /**
     * 同步功耗平台信息到dcs_statistics_data表
     * @param resourceId
     * @param deviceDenamic
     * @param deviceDetail
     */
    private void syncToStatistics(String resourceId, AliPowerDeviceDenamicVo deviceDenamic, AliPowerDeviceMapVo deviceDetail) {
        Map<MonitorMeter, String> statisticMap = new HashMap<>(14);
        statisticMap.put(MonitorMeter.SERVER_CPU_FREQUENCY,deviceDenamic.getCpu_freq());
        //cpu温度余量
        statisticMap.put(MonitorMeter.SERVER_CPU_MARGIN_TEMPERATURE,deviceDenamic.getCpu_margin_temp());
        statisticMap.put(MonitorMeter.SERVER_CPU_TEMPERATURE,deviceDenamic.getCpu_temp());
        statisticMap.put(MonitorMeter.SERVER_CPU_UTIL,deviceDenamic.getCpu_usage());
        statisticMap.put(MonitorMeter.SERVER_CPU_VR_TEMPERATURE,deviceDenamic.getCpu_vr_temp());
        //内存温度
        statisticMap.put(MonitorMeter.SERVER_DIMMG_TEMPERATURE,deviceDenamic.getDimmg_temp());
        //风扇转速
        statisticMap.put(MonitorMeter.SERVER_FAN_RPM,deviceDenamic.getFan_rpm());
        //机框功率
        statisticMap.put(MonitorMeter.SERVER_FRAME_POWER,deviceDenamic.getFrame_power());
        //入风温度
        statisticMap.put(MonitorMeter.SERVER_INLET_TEMPERATURE,deviceDenamic.getInlet_temp());
        //硬盘温度
        statisticMap.put(MonitorMeter.SERVER_NVME_TEMPERATURE,deviceDenamic.getNvme_temp());
        //出风温度
        statisticMap.put(MonitorMeter.SERVER_OUTLET_TEMPERATURE,deviceDenamic.getOutlet_temp());
        //芯片组温度
        statisticMap.put(MonitorMeter.SERVER_PCH_TEMPERATURE,deviceDenamic.getPch_temp());
        statisticMap.put(MonitorMeter.SERVER_POWER,deviceDenamic.getPower());
        //ps电源功率
        statisticMap.put(MonitorMeter.SERVER_PS_POWER,deviceDenamic.getPs_power());

        log.info("[SyncAliPowerTask]同步监控数据:{}",statisticMap);

        Date collectTime=new Date();
        for (Map.Entry<MonitorMeter,String> statistic:statisticMap.entrySet()){
            if (StringUtils.isEmpty(statistic.getValue())){
                log.info("[SyncAliPowerTask]{}监控数据为空",statistic.getKey().name());
                statistic.setValue("0");
            }
            double value = Arrays.stream(statistic.getValue().split(",")).mapToDouble(Double::valueOf).average().orElse(0D);
            if (statistic.getKey()==MonitorMeter.SERVER_CPU_FREQUENCY){
                value=value/1000;
            }
            StatisticsEntity statisticsEntity=new StatisticsEntity();
            statisticsEntity.setId(UUID.randomUUID().toString());
            statisticsEntity.setMeter(statistic.getKey().getMeter());
            statisticsEntity.setResourceId(resourceId);
            statisticsEntity.setTimestamp(collectTime);
            statisticsEntity.setValue(value);
            statisticsDao.save(statisticsEntity);
        }
    }


}
